﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Xml.Serialization;
using vJine.Core.IO.Xml;
using vJine.Core.IoC;

namespace vJine.Core.Task {
    /// <summary>
    /// 任务计划类
    /// </summary>
    [Serializable]
    [AppConfig("vJine.Net/Cron")]
    public partial class Cron : IComparer<Cron.Job> {
        /// <summary>
        /// 比较任务一致性
        /// </summary>
        /// <param name="job1">任务1</param>
        /// <param name="jbo2">任务2</param>
        /// <returns></returns>
        public int Compare(Cron.Job job1, Cron.Job jbo2) {
            if (job1 == null && jbo2 == null || job1.Next == null && jbo2.Next == null) {
                return 0;
            } else if (job1 == null || job1.Next == null) {
                return -1;
            } else if (jbo2 == null || jbo2.Next == null) {
                return 1;
            } else if (job1 == jbo2) {
                return 0;
            } else {
                DateTime at_x = job1.Next.Value; DateTime at_y = jbo2.Next.Value;
                if (at_x > at_y) {
                    return 1;
                } else if (at_x == at_y) {
                    return 0;
                } else {
                    return -1;
                }
            }
        }
        /// <summary>
        /// 任务集合
        /// </summary>
        [XmlArray("Jobs")]
        public List<Job> Jobs { get; set; }
        /// <summary>
        /// 实例化任务计划类
        /// </summary>
        public Cron() {
            this.Jobs = new List<Job>();

        }
        /// <summary>
        /// 开始任务计划
        /// </summary>
        public void Start() {
            if (this.Jobs.Count == 0) {
                return;
            }
            DateTime now = DateTime.Now;
            for (int i = 0, len = this.Jobs.Count; i < len; i++) {
                this.Jobs[i].SetNext(now);
            }
            this.Jobs.Sort(this);

            this.tmr_daemon =
                new Timer(new TimerCallback(this.task_daemon), null, 0, Timeout.Infinite);
        }

        Timer tmr_daemon = null;
        /// <summary>
        /// 任务执行事件
        /// </summary>
        public event Exec<Job> OnTask;
        long period = Timeout.Infinite;

        void task_daemon(object obj) {
            for (int i = 0; i < this.Jobs.Count; ) {
                DateTime now = DateTime.Now;
                Job job_i = this.Jobs[i];

                if (job_i.Next == null) {
                    this.Jobs.Remove(job_i);
                    continue;
                } else if (job_i.Next <= now) {
                    this.OnTask.BeginInvoke(job_i, null, null);

                    if (job_i.SetNext(DateTime.Now) == null) {
                        this.Jobs.Remove(job_i); continue;
                    } else {
                        this.Jobs.Sort(this);
                        i = 0; continue;
                    }
                } else {
                    this.tmr_daemon.Change(job_i.get_duetime(now), this.period);
                    return;
                }
            }

            if (this.Jobs.Count > 0) {
                this.Jobs.Sort(this);
                this.tmr_daemon.Change(
                    this.Jobs[0].get_duetime(), this.period);
            }
        }
        /// <summary>
        /// 保存任务计划到指定的配置文件
        /// </summary>
        /// <param name="cron">任务计划</param>
        /// <param name="cron_file">制定的配置文件</param>
        public static void Save(Cron cron, string cron_file) {
            XmlHelper.ToString<Cron>(cron, cron_file);
        }
        /// <summary>
        /// 从指定的配置文件读取任务计划
        /// </summary>
        /// <param name="cron_file">指定的配置文件</param>
        /// <returns>任务计划实例</returns>
        public static Cron Load(string cron_file) {
            return XmlHelper.Parse<Cron>(cron_file);
        }
    }
}
